/**
 * Copyright 2008 Mathias Doenitz, http://lis.to/
 *
 * This file is part of the lis.to java desktop client. The lis.to java desktop client is free software: you can
 * redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * The lis.to java desktop client is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with the lis.to java desktop client.
 * If not, see http://www.gnu.org/licenses/
 */

package listo.client.dialogs;

import com.google.inject.Inject;
import listo.client.ContextManager;
import listo.client.ImageProvider;
import listo.client.MainForm;
import listo.client.Preferences;
import listo.client.dialogs.controllers.PopupSnoozeTimeController;
import listo.client.model.Context;
import listo.client.model.Tasks;
import listo.client.model.operations.Operation;
import listo.client.tasklists.PopupTaskList;
import listo.utils.reflection.Reflector;
import listo.utils.types.Copyable;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class PopupDialog extends BaseDialog<PopupDialog.Model> {

    public static class Model implements Copyable<Model> {
        public final Tasks tasks;
        public Integer snoozeTime;

        public Model(Tasks tasks, Integer snoozeTime) {
            this.tasks = tasks;
            this.snoozeTime = snoozeTime;
        }

        public Model copy() {
            return this; // somewhat of a hack, but we don't need copying of this object
        }
    }

    private final PopupTaskList popupTaskList;
    private final ContextManager contextManager;
    private final PopupSnoozeTimeController snoozeTimeController;

    private JTextField snoozeTimeTextField;
    private int enableCounter;

    @Inject
    public PopupDialog(MainForm mainForm, PopupTaskList popupTaskList, ContextManager contextManager,
                       ImageProvider imageProvider, Reflector reflector, Preferences preferences,
                       PopupSnoozeTimeController snoozeTimeController) {
        super(mainForm.isVisible() ? mainForm : null, imageProvider, reflector);
        this.popupTaskList = popupTaskList;
        this.contextManager = contextManager;
        this.snoozeTimeController = snoozeTimeController;

        enableCounter = preferences.getEnabledDelay();
    }

    public void run(Model modelObject) {
        final ContextManager.ContextChangedListener contextChangedListener = new ContextManager.ContextChangedListener() {
            // CAUTION: This method is being called from the context thread.
            public void currentContextChanged(final Context context, Operation undoOp, Operation redoOp) {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        popupTaskList.update(context.getTasks());
                        boolean canSnooze = !popupTaskList.isEmpty() && popupTaskList.someActive();
                        buttonOk.setText(canSnooze ? "Snooze" : "Ok");
                        snoozeTimeTextField.setEnabled(canSnooze);
                    }
                });
            }
        };
        contextManager.addContextChangedListener(contextChangedListener);

        addWindowListener(new WindowAdapter() {
            public void windowClosed(WindowEvent e) {
                contextManager.removeContextChangedListener(contextChangedListener);
            }
        });

        super.run(modelObject);
    }

    private void updateOkButton() {
        buttonOk.setText(enableCounter > 0 ? String.format("Snooze (%1$s)", enableCounter) : "Snooze");
    }

    protected void setButtonOKEnabled(boolean enabled) {
        buttonOk.setEnabled(enabled && enableCounter <= 0);
    }

    protected void onOk() {
        if (!snoozeTimeTextField.isEnabled()) modelObject.snoozeTime = null;
        super.onOk();
    }

    protected void createUI() {
        super.createUI();

        setTitle("lis.to Task Reminder");

        JLabel taskLabel = new JLabel("You asked to be reminded of the following tasks");
        JScrollPane scrollPane = new JScrollPane(popupTaskList);
        taskLabel.setLabelFor(popupTaskList);
        popupTaskList.setEnabled(false);

        JLabel snoozeTimeLabel = new JLabel("Snooze time");
        snoozeTimeTextField = new JTextField();
        snoozeTimeLabel.setLabelFor(snoozeTimeTextField);
        attach(snoozeTimeTextField, snoozeTimeController);

        buttonOk.setFont(UIManager.getFont("Button.font").deriveFont(Font.BOLD, 13));
        buttonOk.setEnabled(false);
        updateOkButton();
        new Timer(1000, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                enableCounter--;
                updateOkButton();
                if (enableCounter <= 0) {
                    buttonOk.setEnabled(true);
                    popupTaskList.setEnabled(true);
                    ((Timer) e.getSource()).stop();
                }
            }
        }).start();

        layout.setAutoCreateContainerGaps(true);
        layout.setAutoCreateGaps(true);

        layout.setHorizontalGroup(
                layout.createParallelGroup().
                        addComponent(taskLabel).
                        addComponent(scrollPane, 400, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE).
                        addGroup(GroupLayout.Alignment.LEADING, layout.createSequentialGroup().
                        addComponent(snoozeTimeLabel).
                        addComponent(snoozeTimeTextField).
                        addComponent(buttonOk, 150, 150, 150)));
        layout.setVerticalGroup(
                layout.createSequentialGroup().
                        addComponent(taskLabel).
                        addComponent(scrollPane, 50, 100, Short.MAX_VALUE).
                        addGroup(layout.createParallelGroup().
                        addComponent(snoozeTimeLabel).
                        addComponent(snoozeTimeTextField, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE,
                                GroupLayout.PREFERRED_SIZE).
                        addComponent(buttonOk)));

        setContentPane(contentPane);
        firstFocusComponent = popupTaskList;

        popupTaskList.setTasks(PopupDialog.this.modelObject.tasks);
    }
}
